<template>
  <div
    class="video-play-back"
    :id="state.pid"
    :class="{ 'landscape-mode': props.isLandscape }"
  ></div>
</template>

<script setup>
import {
  reactive,
  onMounted,
  onBeforeUnmount,
  watch,
  defineEmits,
  defineProps,
  defineExpose,
} from "vue";
import dayjs from "dayjs";
import { ElMessage } from "element-plus";
import { getPointUrl, getPointUrlBack, talkToseppk } from "@/api/event.js";
const emit = defineEmits(["capImg"]);
const props = defineProps({
  vid: String,
  Times: Array,
  url: String,
  capUrl: {
    type: Boolean,
    default: false,
  },
  resolution: {
    type: String,
    default: "1",
  },
  isLandscape: {
    type: Boolean,
    default: false,
  },
});

const state = reactive({
  pm: {},
  myPlugin: null,
  curIndex: 0,
  pid: "bk" + Math.floor(Math.random() * 1000) + 1,
  isPlaying: false,
  isPaused: false,
  currentSpeed: 1.0, // 当前播放速度
  isTalking: false, // 是否正在对讲
});

// 初始化播放器
const initPlayer = () => {
  console.log("初始化播放器", state.myPlugin);
  if (state.myPlugin != null) return;

  state.myPlugin = new JSPlugin({
    szId: state.pid,
    szBasePath: "/js/",
    bSupporDoubleClickFull: false,
    iMaxSplit: 1,
    iCurrentSplit: 1,
  });

  state.myPlugin.JS_SetWindowControlCallback({
    windowEventSelect: (index) => {
      state.curIndex = index;
    },
    pluginErrorHandler: (iWndIndex, iErrorCode, oError) => {
      console.error(`window-${iWndIndex}, errorCode: ${iErrorCode}`, oError);
      ElMessage.error(`播放失败, 错误码: ${iErrorCode}`);
      play();
    },
    windowFullCcreenChange: (bFull) => {
      state.myPlugin.JS_Resize();
    },
    StreamEnd: (index) => {
      console.log(`窗口${index}播放结束`);
      state.isPlaying = false;
    },
  });
};

// 播放视频
const play = async () => {
  let ids = [props.vid];
  //根据选择 获取监控点播放地址，尝试播放
  let { data } = await getPointUrl({
    deviceIds: ids,
    ifwww: "1",
    streamType: props.resolution, // 新增：传递分辨率参数
  });

  let urls = data.cameraUrls || [];
  if (urls.length > 0) {
    state.myPlugin.JS_StopRealPlayAll();
    for (let i = 0; i < urls.length; i++) {
      if (i > 8) break;
      state.myPlugin
        .JS_Play(urls[i].cameraUrl, { playURL: urls[i].cameraUrl, mode: 1 }, i)
        .then(
          () => {
            resize();
          },
          (err) => {}
        );
    }
  }
};

// 暂停播放
const pause = async () => {
  console.log("暂停播放", state.curIndex);
  if (state.myPlugin && state.isPlaying) {
    await state.myPlugin.JS_Stop(state.curIndex);
    // state.isPaused = true;
    // state.isPlaying = false;
  }
};

// 快进（30秒）
const seekForward = async (seconds = 30) => {
  if (!state.myPlugin) return;

  try {
    const currentTime = await state.myPlugin.JS_GetOSDTime(state.curIndex);
    const newTime = new Date(currentTime + seconds * 1000);
    await seek(newTime);
  } catch (err) {
    console.error("快进失败:", err);
  }
};

// 快退（30秒）
const seekBackward = async (seconds = 30) => {
  if (!state.myPlugin) return;

  try {
    const currentTime = await state.myPlugin.JS_GetOSDTime(state.curIndex);
    const newTime = new Date(currentTime - seconds * 1000);
    await seek(newTime);
  } catch (err) {
    console.error("快退失败:", err);
  }
};

// 定位到指定时间
const seek = async (targetTime) => {
  if (!state.myPlugin || !targetTime) return;

  const startTime = formatTime(targetTime);
  const endTime = formatTime(new Date(targetTime.getTime() + 3600000));

  await state.myPlugin.JS_Seek(state.curIndex, startTime, endTime);
};

// 时间格式化
const formatTime = (date) => {
  return dayjs(date).format("YYYY-MM-DDTHH:mm:ss.SSSZ");
};

// 设置播放速度
const setSpeed = async (targetSpeed) => {
  if (!state.myPlugin || targetSpeed <= 0) return;

  // H5Player 仅支持 1/8, 1/4, 1/2, 1, 2, 4, 8 倍速
  const supportedSpeeds = [0.125, 0.25, 0.5, 1, 2, 4, 8];
  if (!supportedSpeeds.includes(targetSpeed)) {
    ElMessage.warning(`不支持${targetSpeed}x速度，已自动调整`);
    return;
  }

  // 计算需要调整的次数
  let current = state.currentSpeed;
  while (current !== targetSpeed) {
    if (current < targetSpeed) {
      await state.myPlugin.JS_Fast(state.curIndex);
      current *= 2;
    } else {
      await state.myPlugin.JS_Slow(state.curIndex);
      current /= 2;
    }
  }

  state.currentSpeed = current;
};

// 截图
const toCapImg = () => {
  if (!state.myPlugin) return;

  state.myPlugin.JS_CapturePicture(
    state.curIndex,
    `cap_${Date.now()}`,
    "JPEG",
    (imageData) => {
      const blob = new Blob([imageData], { type: "image/jpeg" });
      const url = URL.createObjectURL(blob);
      emit("capImg", url);
    }
  );
};

// 开始录像
const startRecording = async () => {
  if (!state.myPlugin) return;

  const fileName = `rec_${Date.now()}`;
  await state.myPlugin.JS_StartSaveEx(state.curIndex, fileName, 5); // 5表示MP4格式
  return true;
};

// 停止录像
const stopRecording = async () => {
  if (!state.myPlugin) return;

  await state.myPlugin.JS_StopSave(state.curIndex);
  return true;
};

// 开启声音
const turnOnSound = async () => {
  if (state.myPlugin) {
    await state.myPlugin.JS_OpenSound(state.curIndex);
    return true;
  }
  return false;
};

// 关闭声音
const turnOffSound = async () => {
  if (state.myPlugin) {
    await state.myPlugin.JS_CloseSound(state.curIndex);
    return true;
  }
  return false;
};
// 开始对讲
const startTalk = async (szTalkUrl) => {
  if (!state.myPlugin) {
    throw new Error("播放器实例未初始化");
  }

  if (!szTalkUrl) {
    throw new Error("对讲地址不能为空");
  }

  if (state.isTalking) {
    console.error("已在对讲中");
    return;
  }

  try {
    await state.myPlugin.JS_StartTalk(szTalkUrl);
    state.isTalking = true;
    console.log("对讲已开启");
  } catch (err) {
    state.isTalking = false;
    const errorMsg = err.message || "未知错误";
    // 检查错误码（h5插件返回的错误码可能在 code、errorCode、errCode 等属性中，或者错误对象本身就是错误码）
    let errorCode = err?.code || err?.errorCode || err?.errCode || err?.error;
    
    // 如果错误对象本身是数字或字符串，也可能是错误码
    if (!errorCode && (typeof err === 'number' || typeof err === 'string')) {
      errorCode = err;
    }
    
    // 将错误码和错误对象转换为字符串进行比较
    const errorCodeStr = String(errorCode || err);
    const errStr = String(err);
    const targetErrorCode = '0x12f900008';
    const targetErrorCodeNum = 0x12f900008;
    
    // 如果错误码是 0x12f900008，显示提示（支持多种格式匹配）
    if (
      errorCode === targetErrorCodeNum || 
      errorCode === targetErrorCode || 
      errorCodeStr === targetErrorCode ||
      errorCodeStr.includes('0x12f900008') ||
      errStr.includes('0x12f900008')
    ) {
      ElMessage.error("该设备不支持对讲");
    } else {
      // 其他错误只在控制台输出
      console.error(`对讲启动失败: ${errorMsg}`, "错误码:", errorCode, err);
    }
    
    throw err;
  }
};

// 停止对讲
const stopTalk = async () => {
  if (!state.myPlugin) {
    throw new Error("播放器实例未初始化");
  }

  if (!state.isTalking) {
    console.error("当前未在对讲中");
    return;
  }

  try {
    await state.myPlugin.JS_StopTalk();
    state.isTalking = false;
    console.log("对讲已结束");
  } catch (err) {
    state.isTalking = true;
    const errorMsg = err.message || "未知错误";
    console.error(`对讲停止失败: ${errorMsg}`);
    throw err;
  }
};

// 窗口大小调整
const resize = () => {
  if (state.myPlugin) {
    setTimeout(() => {
      state.myPlugin.JS_Resize();
    }, 50);
  }
};

// 销毁播放器
const destroyPlayer = () => {
  if (state.myPlugin) {
    state.myPlugin.JS_StopRealPlayAll();
    state.myPlugin.JS_DestroyWorker();
    state.myPlugin = null;
  }
};
// 重新加载视频流
const loadVideo = () => {
  // 实现视频加载逻辑（如初始化播放器、请求视频流等）
  console.log("重新加载视频流...");
  play(); // 重新取流
};
// 监听播放地址变化
watch(
  () => props.vid,
  (newVal) => {
    if (newVal) {
      state.isPlaying = false;
      state.isPaused = false;
      play();
    }
  },
  { immediate: true }
);
// 监听分辨率变化，自动重新播放
watch(
  () => props.resolution,
  (newVal) => {
    if (newVal && props.vid) {
      // 分辨率变化且视频ID存在时，重新加载视频
      state.isPlaying = false;
      play(); // 调用play方法重新请求接口
    }
  }
);
// 组件挂载时初始化
onMounted(() => {
  initPlayer();
  window.addEventListener("resize", resize);
});

// 组件卸载时清理
onBeforeUnmount(() => {
  destroyPlayer();
  window.removeEventListener("resize", resize);
  if (state.myPlugin) {
    state.myPlugin.JS_StopRealPlayAll();
    state.myPlugin.JS_DestroyWorker();
    state.myPlugin = null;
  }
});

// 暴露方法给父组件
defineExpose({
  loadVideo,
  resize,
  play,
  pause,
  seekForward,
  seekBackward,
  setSpeed,
  toCapImg,
  startRecording,
  stopRecording,
  turnOnSound,
  turnOffSound,
  startTalk,
  stopTalk,
  getIsTalking: () => state.isTalking, // 获取对讲状态
});
</script>

<style lang="scss" scoped>
.video-play-back {
  width: 100%;
  height: 100%;
}
.landscape-mode {
  position: fixed !important;
  z-index: 99999 !important;
  background: #1c1b1b !important;
  // 关键调整：先居中平移，再旋转，确保旋转后整体居中
  transform: translate(-50%, -50%) rotate(90deg);
  // 旋转后，宽度应等于视口高度，高度等于视口宽度（适配横屏）
  width: 100vh !important;
  height: 100vw !important;
  position: fixed !important; // 固定定位，脱离文档流，避免父容器限制
  top: 50% !important; // 垂直居中基准点
  left: 50% !important; // 水平居中基准点
  margin: 0 !important; // 清除可能的默认边距
  padding: 0 !important; // 清除内边距
  // 覆盖其他可能的限制样式
  max-width: none !important;
  max-height: none !important;
}
</style>
